package com.benio.ycfdisplayer.fresco.photoview;

import android.content.Context;
import android.content.res.ColorStateList;
import android.graphics.Bitmap;
import android.graphics.drawable.Drawable;
import android.net.Uri;
import android.os.Build;
import android.support.annotation.Nullable;
import android.util.AttributeSet;
import android.view.MotionEvent;

import com.benio.ycfdisplayer.fresco.FrescoView;
import com.facebook.drawee.generic.GenericDraweeHierarchyBuilder;
import com.facebook.drawee.generic.GenericDraweeHierarchyInflater;
import com.facebook.drawee.interfaces.DraweeController;
import com.facebook.drawee.interfaces.DraweeHierarchy;
import com.facebook.drawee.view.AspectRatioMeasure;
import com.facebook.drawee.view.DraweeHolder;

import uk.co.senab.photoview.PhotoView;

/**
 * An {@link PhotoView} that displays a {@link DraweeHierarchy}.
 * Created by zhangzhibin on 2016/9/29.
 */
public class FrescoPhotoViewSupport extends PhotoView implements FrescoView {

    private final AspectRatioMeasure.Spec mMeasureSpec = new AspectRatioMeasure.Spec();
    private float mAspectRatio = 0;
    private DraweeHolder<DraweeHierarchy> mDraweeHolder;
    private boolean mInitialised = false;

    public FrescoPhotoViewSupport(Context context) {
        super(context);
        init(context);
        inflateHierarchy(context, null);
    }

    public FrescoPhotoViewSupport(Context context, AttributeSet attr) {
        super(context, attr);
        init(context);
        inflateHierarchy(context, attr);
    }

    public FrescoPhotoViewSupport(Context context, AttributeSet attr, int defStyle) {
        super(context, attr, defStyle);
        init(context);
        inflateHierarchy(context, attr);
    }

    /**
     * This method is idempotent so it only has effect the first time it's called
     */
    private void init(Context context) {
        if (mInitialised) {
            return;
        }
        mInitialised = true;
        mDraweeHolder = DraweeHolder.create(null, context);
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
            ColorStateList imageTintList = getImageTintList();
            if (imageTintList == null) {
                return;
            }
            setColorFilter(imageTintList.getDefaultColor());
        }
    }

    protected void inflateHierarchy(Context context, @Nullable AttributeSet attrs) {
        GenericDraweeHierarchyBuilder builder =
                GenericDraweeHierarchyInflater.inflateBuilder(context, attrs);
        setAspectRatio(builder.getDesiredAspectRatio());
        setHierarchy(builder.build());
    }

    /**
     * Sets the hierarchy.
     */
    public void setHierarchy(DraweeHierarchy hierarchy) {
        mDraweeHolder.setHierarchy(hierarchy);
        super.setImageDrawable(mDraweeHolder.getTopLevelDrawable());
    }

    /**
     * Gets the hierarchy if set, throws NPE otherwise.
     */
    public DraweeHierarchy getHierarchy() {
        return mDraweeHolder.getHierarchy();
    }

    /**
     * Returns whether the hierarchy is set or not.
     */
    public boolean hasHierarchy() {
        return mDraweeHolder.hasHierarchy();
    }

    /**
     * Gets the top-level drawable if hierarchy is set, null otherwise.
     */
    @Nullable
    public Drawable getTopLevelDrawable() {
        return mDraweeHolder.getTopLevelDrawable();
    }

    /**
     * Sets the controller.
     */
    public void setController(@Nullable DraweeController draweeController) {
        mDraweeHolder.setController(draweeController);
        // Do not open this, otherwise PhotoView can not be used properly.
        // super.setImageDrawable(mDraweeHolder.getTopLevelDrawable());
    }

    /**
     * Gets the controller if set, null otherwise.
     */
    @Nullable
    public DraweeController getController() {
        return mDraweeHolder.getController();
    }

    /**
     * Returns whether the controller is set or not.
     */
    public boolean hasController() {
        return mDraweeHolder.getController() != null;
    }

    @Override
    public void onDetachedFromWindow() {
        super.onDetachedFromWindow();
        onDetach();
    }

    @Override
    public void onStartTemporaryDetach() {
        super.onStartTemporaryDetach();
        onDetach();
    }

    @Override
    public void onAttachedToWindow() {
        super.onAttachedToWindow();
        onAttach();
    }

    @Override
    public void onFinishTemporaryDetach() {
        super.onFinishTemporaryDetach();
        onAttach();
    }

    protected void onDetach() {
        mDraweeHolder.onDetach();
    }

    protected void onAttach() {
        mDraweeHolder.onAttach();
    }

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        return mDraweeHolder.onTouchEvent(event) || super.onTouchEvent(event);
    }

    @Override
    protected boolean verifyDrawable(Drawable who) {
        if (who == mDraweeHolder.getTopLevelDrawable()) {
            return true;
        }
        return super.verifyDrawable(who);
    }

    /**
     * Use this method only when using this class as an ordinary ImageView.
     *
     * @deprecated Use {@link #setController(DraweeController)} instead.
     */
    @Override
    @Deprecated
    public void setImageDrawable(Drawable drawable) {
        init(getContext());
        mDraweeHolder.setController(null);
        super.setImageDrawable(drawable);
    }

    /**
     * Use this method only when using this class as an ordinary ImageView.
     *
     * @deprecated Use {@link #setController(DraweeController)} instead.
     */
    @Override
    @Deprecated
    public void setImageBitmap(Bitmap bm) {
        init(getContext());
        mDraweeHolder.setController(null);
        super.setImageBitmap(bm);
    }

    // 提供给Target调用
    void setDrawable(Drawable drawable) {
        super.setImageDrawable(drawable);
    }

    void setBitmap(Bitmap bitmap) {
        super.setImageBitmap(bitmap);
    }

    /**
     * Use this method only when using this class as an ordinary ImageView.
     *
     * @deprecated Use {@link #setController(DraweeController)} instead.
     */
    @Override
    @Deprecated
    public void setImageResource(int resId) {
        init(getContext());
        mDraweeHolder.setController(null);
        super.setImageResource(resId);
    }

    /**
     * Use this method only when using this class as an ordinary ImageView.
     *
     * @deprecated Use {@link #setController(DraweeController)} instead.
     */
    @Override
    @Deprecated
    public void setImageURI(Uri uri) {
        init(getContext());
        mDraweeHolder.setController(null);
        super.setImageURI(uri);
    }

    /**
     * Sets the desired aspect ratio (w/h).
     */
    public void setAspectRatio(float aspectRatio) {
        if (aspectRatio == mAspectRatio) {
            return;
        }
        mAspectRatio = aspectRatio;
        requestLayout();
    }

    /**
     * Gets the desired aspect ratio (w/h).
     */
    public float getAspectRatio() {
        return mAspectRatio;
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        mMeasureSpec.width = widthMeasureSpec;
        mMeasureSpec.height = heightMeasureSpec;
        AspectRatioMeasure.updateMeasureSpec(
                mMeasureSpec,
                mAspectRatio,
                getLayoutParams(),
                getPaddingLeft() + getPaddingRight(),
                getPaddingTop() + getPaddingBottom());
        super.onMeasure(mMeasureSpec.width, mMeasureSpec.height);
    }
}
